/*************************************************
Copyright © FJ Ltd. 2025 All rights reserved(版权所有).
File name: 链表结构（单链接、双链表、循环链表等）
Author:ZLG
Version: V1.0.0
Description: // 用于详细说明此程序文件完成的主要功能，与其他模块或函数的接口，输出值、取值范围、含义及参数间的控；制、顺序、独立或依赖等关系
Others:      // 其它内容的说明
Log:         // 修改日志，包括修改内容，日期，修改人等
Date            Author          Version      Comment/Description
2025/03/28       ZLG            V1.0.0            修改内容
*************************************************/
#include "LinkedList.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

/**
***********************************************************************
* @brief   初始化链表
* @param   LinkedList *header 链表头部（头结点）指针
* @retval  无
* @note  无
***********************************************************************
*/
void initLinkedList(LinkedList *list)
{
	list->head = NULL;//不知道是否存在节点，将其设置为空指针
	list->size = 0;
}

/**
***********************************************************************
* @brief   获取链表长度
* @param   LinkedList *header 链表头部（头结点）指针
* @retval  链表长度--header->size
* @note  无
***********************************************************************
*/
size_t getLength(const LinkedList *list)
{
	return list->size;
}

/**
***********************************************************************
* @brief   在链表指定位置插入元素
* @param   LinkedList *list, size_t index, int element
* @retval  无
* @note  无
***********************************************************************
*/
void insertAt(LinkedList *list, size_t index, int element)
{
	/* 
		1、申请链表节点内存
		2、插入位置的索引不能超出链表大小
		3、在链表头部插入元素
		4、在链表中间插入元素
		5、在链表末尾插入元素
	*/
	/*1、申请链表节点内存*/
	Node *node =(Node*)malloc(sizeof(Node) * 1);//申请插入节点需要的内存空间
	node->data = element;//将数据元素插入新的节点中

	/*判断内存申请是否成功*/
	if(node == NULL)
	{
		printf("内存申请失败\n");
		return;
	}
	printf("内存申请成功\n");

	/* 2、插入元素不合法*/
	if(index < 0 || index > list->size)
	{
		printf("插入元素不合法\n");
		return;
	}

	/* 2、在链表头部插入元素 */
	if(index == 0)
	{
		node->next = list->head;//将链表首节点的地址存放在新插入的节点中
		list->head = node;//将新插入节点地址存放在链表头部指针中
		list->size++;
		return;
	}
	/* 4、在链表中间和末尾插入插入元素 */
	else if(index <= list->size)
	{
		Node *current_node =  list->head;//定义一个当前链表节点，并赋值为链表头节点
		for(size_t i = 0; i < index - 1; i++)
		{
			current_node = current_node->next;
		}
		node->next = current_node->next;
		current_node->next = node;
		list->size++;
		return;
	}
}

/**
***********************************************************************
* @brief   在链表末尾插入元素
* @param   LinkedList *list, int element
* @retval  无
* @note  
***********************************************************************
*/
void insertEnd(LinkedList *list, int element)
{
	insertAt(list, list->size, element);
}

/**
***********************************************************************
* @brief   删除链表中的指定元素, 并返回被删除的函数
* @param   
* @retval  
* @note  
***********************************************************************
*/
int deleteAt(LinkedList *list, size_t index)
{
		/* 
		1、链表头指针为空,即判断链表是不是空链表
		2、删除位置的索引不能超出链表大小
		3、在链表头部删除元素
		4、在链表中间删除元素
		5、在链表末尾删除元素
	*/
	/* 1、 链表头部指针为空 */
	if(list->head == NULL)
	{
		printf("链表头部指针为空");
		return -1;
	}
	/* 2、删除位置索引不超出链表大小 */
	if(index < 0 || index >= list->size)
	{
		printf("输入的index不合法");
		return -1;
	}
	
	/* 3、删除链表头部元素 */
	if(index == 0)
	{	
		Node *deleteNode = list->head;//定义一个需要删除的节点deleteNode
		list->head = deleteNode->next;//将链表头节点重新指向所删除节点的下一个节点

		list->size--;//链表大小减1
		return deleteNode->data;//返回删除链表节点的元素
		free(deleteNode);//并释放删除节点的内存空间
	}
	/* 4、删除中间元素和末尾元素 */
	else 
	{
		Node *currentNode = list->head; 
		for(int i = 0; i < index - 1; i++)
		{
			currentNode = currentNode->next;
		}
		Node *deleteNode = currentNode->next;
		currentNode->next = deleteNode->next;
		list->size--;
		return deleteNode->data;
		free(deleteNode);
	}
}

/**
***********************************************************************
* @brief   删除链表末尾元素
* @param   LinkedList *list
* @retval  返回被删除的值
* @note  
***********************************************************************
*/
int deleteEnd(LinkedList *list)
{
	return deleteAt(list, list->size-1);
}


/**
***********************************************************************
* @brief   修改链表中指定元素的值
* @param   LinkedList *list, size_t index, int new_element
* @retval  
* @note  
***********************************************************************
*/
void modifyAt(const LinkedList *list, size_t index, int newValue)
{
	if(list->head == NULL)
	{
		printf("链表为空");
		return;
	}
	if(index < 0 || index >= list->size)
	{
		printf("查询的index不合法");
		return;
	}
	Node *currentNode = list->head;
	for(int i = 0; i < index; i++)
	{
		currentNode = currentNode->next;
	}
	currentNode->data = newValue;
}

/**
***********************************************************************
* @brief   获取指定位置的元素
* @param   const LinkedList *list：链表指针, size_t index：获取链表元素索引
* @retval  获取到的元素
* @note  
***********************************************************************
*/
int getElementAt(const LinkedList *list, size_t index)
{
	if(list->head == NULL)
	{
		printf("链表为空");
		return -1;
	}
	if(index < 0 || index >= list->size)
	{
		printf("查询的index不合法");
		return -1;
	}
	Node *currentNode = list->head;
	for(int i = 0; i < index; i++)
	{
		currentNode = currentNode->next;
	}
	return currentNode->data;
}

/**
***********************************************************************
* @brief   遍历链表中所有的元素
* @param   LinkedList *list：链表指针（整个链表）
* @retval  无
* @note  
***********************************************************************
*/
void printAt(LinkedList *list)
{
	Node *currentNode = list->head;
	for(int i =0; i < list->size; i++)
	{
		Node *tempNode = currentNode;
		printf("%d\n", tempNode->data);
		currentNode = currentNode->next;
	}

	// Node *currentNode = list->head;
	// printf("%d\n", currentNode->data);
	// while(currentNode->next != NULL)
	// {
	// 	currentNode = currentNode->next;
	// 	printf("%d\n", currentNode->data);
	// }
}

/**
***********************************************************************
* @brief   释放链表内存
* @param   LinkedList *list
* @retval  
* @note  
***********************************************************************
*/
void destroyLinkedList(LinkedList *list)
{
	Node *currentNode = list->head;
	for(int i = 0; i < list->size; i++)
	{
		Node *tempNode = currentNode;
		currentNode = currentNode->next;
		free(tempNode);
	}
	list->head = NULL;//将链表头节点设置为空
	list->size =0;//将链表长度设置为0
}